package handle

import (
	"common/db/fields"
	"common/uuid"
	"fmt"
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"strconv"
	"strings"
)

func (h *Handle) GetObject(ctx *gin.Context) {
	objectName := ctx.Param("object")
	res, err := h.project.DetailObject(ctx, "default", objectName)
	if err != nil {
		ctx.AbortWithError(404, err)
		return
	}
	streamId, _ := uuid.FromBytes(res.StreamId)
	ctx.Header("Etags", streamId.String())
	attr := fields.Attribute(res.Attributes)
	if ct := attr.ContentType(); ct != "" {
		ctx.Header("Content-Type", ct)
	}
	//ctx.Header("Accept-Ranges", "bytes")
	rg := ctx.Request.Header.Get("Range")
	if res.PlainSize > 2000000 {
		ctx.Header("Accept-Ranges", "bytes")
	} else {
		ctx.Header("Accept-Ranges", "none")
		rg = ""
	}
	//ctx.Header("Content-Type", "application/octet-stream")
	//ctx.Header("Content-Type", "video/mp4")
	//ctx.Header("Content-Disposition", "inline")
	if rg != "" {
		if rg[0:6] != "bytes=" {
			ctx.AbortWithStatus(400)
			return
		}
		arr := strings.SplitN(rg[6:], "-", 2)
		st, _ := strconv.ParseInt(arr[0], 10, 64)
		et, _ := strconv.ParseInt(arr[1], 10, 64)
		if arr[1] == "" {
			et = res.PlainSize - 1
		}
		if et > res.PlainSize-1 || st >= et {
			ctx.AbortWithStatus(416)
			return
		}

		ctx.Header("Content-Range", fmt.Sprintf("bytes %d-%d/%d", st, et, res.PlainSize))
		ctx.Header("Content-Length", fmt.Sprintf("%d", et-st+1))
		ctx.Status(206)
		err = h.project.DownloadObjectRange(ctx, "default", objectName, st, et-st+1, ctx.Writer)
	} else {
		ctx.Header("Content-Length", fmt.Sprintf("%d", res.PlainSize))
		err = h.project.DownloadObject(ctx, "default", objectName, ctx.Writer)
	}
	if err != nil {
		h.log.Error("download object error", zap.Error(err))
		ctx.Status(500)
	}
	return
}

func (h *Handle) PutObject(ctx *gin.Context) {
	//objectName := ctx.Param("object")
	err := ctx.Request.ParseMultipartForm(h.maxSize)
	if err != nil {
		//ErrNotMultipart
		ctx.AbortWithError(400, err)
		return
	}

	fp, handle, err := ctx.Request.FormFile("file")
	//fmt.Println(objectName, handle.Size, handle.Filename, handle.Header, err)
	//fmt.Println(ctx.Request.ParseMultipartForm())
	fmt.Println(ctx.Request.Header.Get("Content-Type"))
	fmt.Println(handle.Filename, handle.Header)

	key, ok := ctx.GetPostForm("key")
	if !ok || key == "" {
		key = handle.Filename
	}
	attr := fields.Attribute{}
	if ct := handle.Header.Get("Content-Type"); ct != "" {
		attr.SetContentType(ct)
	}

	err = h.project.UploadObject(ctx, "default", key, fp, false, handle.Size, attr)
	if err != nil {
		//ErrNotMultipart
		ctx.AbortWithError(500, err)
	} else {
		ctx.JSON(200, gin.H{"key": key, "bucket": "default"})
	}
	return
}

func (h *Handle) HeadObject(ctx *gin.Context) {
	objectName := ctx.Param("object")
	res, err := h.project.DetailObject(ctx, "default", objectName)
	if err != nil {
		ctx.AbortWithError(500, err)
		return
	}
	streamId, _ := uuid.FromBytes(res.StreamId)
	ctx.Header("Etags", streamId.String())
	ctx.Header("Accept-Ranges", "bytes")
	//ctx.Header("Content-Type", "application/octet-stream")
	//ctx.Header("Content-Type", "video/webm")
	ctx.Header("Content-Length", fmt.Sprintf("%d", res.PlainSize))
	ctx.Status(200)
	return
}
